﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace CrushCrumbleChomp
{
    /// <summary>
    ///     Represents an animated or static sprite with fixed frame sizes.
    /// </summary>
    class Sprite
    {
        /// <summary>
        ///     Controls whether this object has its Update and Draw functions called
        /// </summary>
        public bool exists;
        /// <summary>
        ///     Controls whether this object has its Update function called
        /// </summary>
        public bool active;
        /// <summary>
        ///     Controls whether this object has its Draw function called
        /// </summary>
        public bool visible;
        /// <summary>
        ///     Onscreen coordinates of the sprite
        /// </summary>
        public Vector2 position;
        /// <summary>
        ///     Speed of the sprite
        /// </summary>
        public Vector2 velocity;
        /// <summary>
        ///     The rate of change in speed of the sprite
        /// </summary>
        public Vector2 acceleration;


        /// <summary>
        ///     The spritesheet of our animated or static sprite
        /// </summary>
        Texture2D _textureImage;
        /// <summary>
        ///     List of animations that have been added to this sprite
        /// </summary>
        protected List<Animation> _animations;
        /// <summary>
        ///     Current animation being played
        /// </summary>
        protected Animation _currentAnimation;
        /// <summary>
        ///     Size of each individual frame in the animation
        /// </summary>
        protected Point _frameSize;
        /// <summary>
        ///     Number of animation frames width by length
        /// </summary>
        Point sheetSize;
        /// <summary>
        ///     Current animation frame
        /// </summary>
        Point currentFrame;

        long _frameTimer = 0;

        int millisecondsPerFrame;

        /// <summary>
        ///     Constant default frame value, roughly 60 FPS
        /// </summary>
        const int defaultMillisecondsPerFrame = 16;
        protected float scale;

        public Sprite(Vector2 position)
        {
            this.exists = true;
            this.active = true;
            this.visible = true;
            
            this.position = position;
            this.velocity = Vector2.Zero;
            this.acceleration = Vector2.Zero;

            this._currentAnimation = null;
            this.currentFrame = new Point(0, 0);
        }

        public Sprite LoadGraphic(String filename, Game game, Boolean animated = false, Boolean reverse = false, int width = 0, int height = 0)
        {
            _textureImage = game.Content.Load<Texture2D>(filename);

            if (width == 0)
            {
                if (animated)
                {
                    width = _textureImage.Bounds.Height;
                }
                else
                {
                    width = _textureImage.Bounds.Width;
                }
            }
            _frameSize.X = width;

            if (height == 0)
            {
                if (animated)
                {
                    height = width;
                }
                else
                {
                    height = _textureImage.Bounds.Height;
                }
            }
            _frameSize.Y = height;

            return this;
        }

        public virtual void Update(GameTime gameTime)
        {
            if (_currentAnimation != null)
            {
                // Something something something here
            }

            if (exists && active)
            {
                _frameTimer += gameTime.ElapsedGameTime.Ticks * TimeSpan.TicksPerMillisecond;
                if (_frameTimer > _currentAnimation.delay)
                {
                    _frameTimer -= millisecondsPerFrame;
                    ++currentFrame.X;
                    if (currentFrame.X >= sheetSize.X)
                    {
                        currentFrame.X = 0;
                        ++currentFrame.Y;
                        if (currentFrame.Y >= sheetSize.Y)
                            currentFrame.Y = 0;
                    }
                }
            }
        }

        public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            if (exists && visible)
            {
                spriteBatch.Draw(_textureImage, position, new Rectangle(currentFrame.X * _frameSize.X, currentFrame.Y * _frameSize.Y, _frameSize.X, _frameSize.Y), Color.White, 0, Vector2.Zero, scale, SpriteEffects.None, 0);
            }
        }

        public void AddAnimation(string name, List<Rectangle> frames, uint frameRate = Animation.DEFAULT_FRAME_RATE, bool looped = true)
        {
            _animations.Add(new Animation(name, frames, frameRate, looped));
        }

    }
}
